package es.tid.jala.javame;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;

/**
 * @author jala
 */
public class GetPostMidlet extends MIDlet implements CommandListener {
    private static final String URL = "http://www.comp.leeds.ac.uk";
    private static final String ACTION = "/cgi-bin/Perl/environment-example";
    private static final String QUERY = "review=";

//    private static final String URL = "http://json-time.appspot.com";
//    private static final String ACTION = "/time.json";
//    private static final String QUERY = "tz=";

    private Form form;
    private Alert alertaError;
    private Command getCommand,  postCommand,  salirCommand;
    private TextField tfDatos;
    private StringItem respuesta;
    private String mensajeError;

    public GetPostMidlet() {
        salirCommand = new Command("Salir", Command.EXIT, 1);
        getCommand = new Command("GET", Command.SCREEN, 2);
        postCommand = new Command("POST", Command.SCREEN, 2);

        tfDatos = new TextField("Datos:", "Europe/Madrid", 20, TextField.ANY);

        respuesta = new StringItem("Respuesta: ", "");

        form = new Form("Información");
        form.addCommand(salirCommand);
        form.addCommand(getCommand);
        form.addCommand(postCommand);

        form.append(tfDatos);
        form.append(respuesta);

        form.setCommandListener(this);
    }
    
    
    public void startApp() {
        getDisplay().setCurrent(form);
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }

    public Display getDisplay() {
        return Display.getDisplay(this);
    }

    public void commandAction(Command c, Displayable d) {
        if (c == getCommand || c == postCommand) {
            try {
                if (c == getCommand) {
                    respuesta.setText("GET: conectando...");
                    Runnable r = new Runnable() {
                        public void run() {
                            try {
                                consultarConGET();
                            } catch (IOException ex) {
                                ex.printStackTrace();
                            }
                        }
                    };
                    new Thread(r).start();
                } else {
                    respuesta.setText("POST: conectando...");
                    Runnable r = new Runnable() {

                        public void run() {
                            try {
                                consultarConPOST();
                            } catch (IOException ex) {
                                ex.printStackTrace();
                            }
                        }
                    };
                    new Thread(r).start();
                }
            } catch (Exception e) {
                System.err.println(e.toString());
            }
        } else if (c == salirCommand) {
            destroyApp(false);
            notifyDestroyed();
        }
    }

    private void consultarConGET() throws IOException {
        HttpConnection http = null;
        InputStream is = null;
        boolean result = false;

        // Con GET los datos se pasan al final de la url
        String url = URL + ACTION + "?" + QUERY + tfDatos.getString();

        try {
            http = (HttpConnection) Connector.open(url);

            // Petición desde el cliente
            //-----------------------------
            // Se fijan los datos de la petición
            // método: GET
            http.setRequestMethod(HttpConnection.GET);
            // información de cabecera: opcional para GET
            http.setRequestProperty("User-Agent", "Profile/MIDP-2.0 Configuration/CLDC-1.0");
            http.setRequestProperty("Content-Language", "es-ES");

            // Enviar datos (con get, ya están al final de la URL)

            // Respuesta desde el servidor
            //-----------------------------
            is = http.openInputStream();
            result = procesarRespuesta(http, is);
        } finally {
            if (is != null) {
                is.close();
            }
            if (http != null) {
                http.close();
            }
        }

        if (result == false) {
            mostrarAlerta("GET:" + mensajeError);
        }
    }

    private void consultarConPOST() throws IOException {
        HttpConnection http = null;
        OutputStream os = null;
        InputStream is = null;
        boolean result = false;

        // Con POST, los datos se pasan separados
        String url = URL + ACTION;

        try {
            // 1) Crear HttpConnection
            http = (HttpConnection) Connector.open(url);

            // Petición desde el cliente
            //-----------------------------
            // 2) Fijar los datos de la petición
            // método: POST
            http.setRequestMethod(HttpConnection.POST);
            // información de cabecera: Content-Type y Content-Length para que funcione POST
            http.setRequestProperty("User-Agent", "Profile/MIDP-2.0 Configuration/CLDC-1.0");
            http.setRequestProperty("Content-Language", "es-ES");
            http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

            // Contenido y longitud del contenido (Content-Length)
            String request_body = QUERY + tfDatos.getString();
            byte data[] = request_body.getBytes();
            http.setRequestProperty("Content-Length", String.valueOf(data.length));

            // 3) Se abre el output stream en la conexión para enviar los datos
            os = http.openOutputStream();
            os.write(data);
            
            // Respuesta desde el servidor
            //-----------------------------
            is = http.openInputStream();
            result = procesarRespuesta(http, is);
        } finally {
            if (is != null) {
                is.close();
            }
            if (os != null) {
                os.close();
            }
            if (http != null) {
                http.close();
            }
        }

        if (result == false) {
            mostrarAlerta(mensajeError);
        }

    }

    private boolean procesarRespuesta(HttpConnection http, InputStream is) throws IOException {
        StringBuffer sb = new StringBuffer();
        mensajeError = null;

        sb.append(http.getResponseCode());
        sb.append(' ');
        sb.append(http.getResponseMessage());
        sb.append('\n');
        sb.append('\n');
        
        // 1) Obtener estado
        if (http.getResponseCode() == HttpConnection.HTTP_OK) {

            // 2) Obtener info de la cabecera (si interesa)
            int i = 0;
            while(http.getHeaderFieldKey(i) != null) {
                String headerName = http.getHeaderFieldKey(i);
                sb.append(headerName);
                sb.append(": ");
                sb.append(http.getHeaderField(headerName));
                sb.append('\n');
                i++;
            }
            sb.append('\n');

            // 3) Obtener datos
            int length = (int) http.getLength();
            String str;
            if (length != -1) {
                byte datos[] = new byte[length];
                is.read(datos);
                str = new String(datos);
            } else { // longitud no disponible
                ByteArrayOutputStream baos = new ByteArrayOutputStream();

                int ch;
                while ((ch = is.read()) != -1) {
                    baos.write(ch);
                }

                str = new String(baos.toByteArray());
                baos.close();
            }
            sb.append(str);
            sb.append('\n');
        } else {
            mensajeError = http.getResponseCode() + ": " + http.getResponseMessage();
        }

        // Actualizar la cadena de respuesta
        respuesta.setText(sb.toString());

        return (http.getResponseCode() == HttpConnection.HTTP_OK);
    }

    private void mostrarAlerta(String msg) {
        // Crear alerta con el mensaje recibido del servlet
        alertaError = new Alert("Error", msg, null, AlertType.ERROR);
        alertaError.setTimeout(Alert.FOREVER);
        getDisplay().setCurrent(alertaError, form);
    }

}
